package ai.tubes.iris;

import java.util.ArrayList;
import java.util.Random;

import ai.tubes.iris.helper.Utilities;
import ai.tubes.iris.model.IrisPixel;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.PointF;
import android.os.Bundle;
import android.util.Log;

public class CameraSolutionActivity extends Activity {
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.solution);
		//mImage = (ImageView)findViewById(R.id.image);
		computeIris();
		calculateIrisPixels();
		
		startActivity(new Intent(getApplicationContext(), ResultActivity.class));
		finish();
	}
	
	
	private void computeIris() {
		/** dapatkan gambarnya */
		byte[] imageData = Utilities.sTempImageByteArray;
		Utilities.sTempImageByteArray = null;
		Bitmap bm = BitmapFactory.decodeByteArray(imageData, 0, imageData.length);
		imageData = null;
		System.gc();
		
		/** rotate gambarnya */
		mImageWidth = bm.getWidth();
		mImageHeight = bm.getHeight();
		Matrix m = new Matrix();
		m.postRotate(90);
		
		Bitmap bm2 = Bitmap.createBitmap(bm, 0, 0, mImageWidth, mImageHeight, m, true);
		bm.recycle();
		System.gc();
		bm = bm2;
		
		/** convert jadi grayscale */
		bm2 = Bitmap.createBitmap(mImageHeight, mImageWidth, Bitmap.Config.ARGB_8888);
		mImageWidth = bm2.getWidth();
		mImageHeight = bm2.getHeight();
		Canvas c = new Canvas(bm2);
		/*float[] mx = {
				 -1.0f,  0.0f,  0.0f,  1.0f,  0.0f,
				 0.0f,  -1.0f,  0.0f,  1.0f,  0.0f,
				 0.0f,  0.0f,  -1.0f,  1.0f,  0.0f,
				 0.0f,  0.0f,  0.0f,  1.0f,  0.0f
				};*/
		ColorMatrix cm = new ColorMatrix();
		cm.setSaturation(0);
		Paint p = new Paint();
		ColorMatrixColorFilter f = new ColorMatrixColorFilter(cm);
		p.setColorFilter(f);
		c.drawBitmap(bm, 0, 0, p);
		
		mFlood	= new int[bm2.getHeight()][bm2.getWidth()];
		/** binarization */
		for (int y = 0; y < bm2.getHeight(); ++y){
			for (int x = 0; x < bm2.getWidth(); ++x) {
				int haha = bm2.getPixel(x, y);
				if ((haha & 255) < 11) {
					//bm2.setPixel(x, y, 0xff000000);
					int topLeft = 0, left = 0, top = 0;
					
					if (x - 1  > 0 && y - 1 > 0) topLeft = mFlood[y - 1][x - 1];
					if (x - 1 > 0) left = mFlood[y][x-1];
					if (y - 1 > 0) top = mFlood[y - 1][x];
					
					mFlood[y][x] = 1 + Math.min(topLeft, Math.min(top, left));
				} else {
					//bm2.setPixel(x, y, 0xffffffff);
					mFlood[y][x] = 0;
				}
			}
		}
		
		bm.recycle();
		bm = null;
		System.gc();
		
		Log.i("Camera", "Bitmap size" + mImageWidth + " " + mImageHeight);
		
		mBigBlacked = new ArrayList<Point>();
		
		for (int y = 0; y < bm2.getHeight(); ++y){
			for (int x = 0; x < bm2.getWidth(); ++x) {
				if (mFlood[y][x] > 25) mBigBlacked.add(new Point(x, y));
			}
		}
		
		Log.i("Camera", "Blacked area = " + mBigBlacked.size());
		
		/** isi bm2 saat ini : hasil binarization, bm = image biasa */
		
		if (mBigBlacked.size() > 0) {
			mCenter = new Point(mBigBlacked.get(0));
			for (int i = 1; i < mBigBlacked.size(); ++i) {
				mCenter.x += mBigBlacked.get(i).x;
				mCenter.y += mBigBlacked.get(i).y;
			} 
			
			mCenter.x /= mBigBlacked.size();
			mCenter.y /= mBigBlacked.size();
			
			Log.i("Camera", "Center = " + mCenter);
			
			PointF keluar = new PointF(mCenter);
			
			Random rand = new Random();
			float randMoveY = rand.nextFloat() * (1 - rand.nextInt(2) * 2);
			int randMoveX = (1 - rand.nextInt(2) * 2);
			
			/** memberi tanda ke gambar kalo posisi ke luar iris */
			while (mFlood[(int)keluar.y][(int)keluar.x] > 0) {
				//bm2.setPixel((int)keluar.x, (int)keluar.y, 0xff00ff00);
				keluar.x += randMoveX;
				keluar.y += randMoveY;
			}
			
			float distX = keluar.x - mCenter.x;
			float distY = keluar.y - mCenter.y;
			float tempRad = 0;
			mIrisRadius = (float)Math.sqrt(distX * distX + distY * distY);
			
			/** memberi tanda ke gambar kalo posisi titik pusat */
			/*for (int i = -10; i < 10; ++i) for (int j = -10; j < 10; ++j)
				bm2.setPixel(center.x + i, center.y + j, 0xff0000ff);*/
			
			Log.i("Camera", "Iris radius = " + mIrisRadius);
			
			/** nyari titik2 digambar berwarna yang ada didalam iris */
			mIris = new ArrayList<IrisPixel>();
			mFlood = null;
			System.gc();
			mBigBlacked.clear();
			mBigBlacked = null;
			System.gc();
			
			for (int y = 0; y < bm2.getHeight(); ++y){
				for (int x = 0; x < bm2.getWidth(); ++x) {
					distX = x - mCenter.x;
					distY = y - mCenter.y;
					tempRad = (float)Math.sqrt(distX * distX + distY * distY);
					
					if (tempRad <= mIrisRadius) {
						mIris.add(new IrisPixel(new Point(x, y), bm2.getPixel(x, y)));
						//bm2.setPixel(x, y, 0xffff0000);
					}
				}
			}
			
			Log.i("Camera", "iris pixel count = " + mIris.size());
		}
		
		bm2.recycle();
		bm2 = null;
		System.gc();

		//mImage.setImageBitmap(bm);
	}
	
	private void calculateIrisPixels(){
		int[] pixelValue = new int[256];
		int ambang = 0;
		int kurangDariAmbang = 0;
		float kepadatanTotal = 100;
		float[] kepadatanSudut = new float[20];
		int [] totalPixelSudut = new int[20];
		double deltaSudut = 360 / 19.0f;
		
		/** cari ambang */
		for (int i = 0; i < pixelValue.length; ++i)
			pixelValue[i] = 0;
		
		for (int i = 0; i < mIris.size(); ++i)
			++pixelValue[mIris.get(i).getColor() & 255];
		
		for (int i = 1; i < pixelValue.length; ++i) {
			if (pixelValue[ambang] < pixelValue[i])
				ambang = i;
		}
		
		/** cari yang dibawah ambang */
		for (int i = 0; i < mIris.size(); ++i) {
			IrisPixel item = mIris.get(i);
			double sudut = Math.toDegrees(Math.atan2((double)(item.getPosition().y - mCenter.y),(double)item.getPosition().x - mCenter.x));
			if (sudut < 0) sudut = 360 + sudut;
			//Log.i("Camera Sol", "" + (int)(sudut / deltaSudut));
			++totalPixelSudut[(int)(sudut / deltaSudut)];
			if ((item.getColor() & 255) < ambang) {
				++kurangDariAmbang;
				++kepadatanSudut[(int)(sudut / deltaSudut)];
			}
		}
		
		/** cari kepadatan */
		kepadatanTotal = kurangDariAmbang / mIris.size();
		for (int i = 0;i < totalPixelSudut.length; ++i) {
			if (totalPixelSudut[i] == 0) continue;
			kepadatanSudut[i] = ((float)kepadatanSudut[i] / totalPixelSudut[i]) * 100.0f;
		}
		
		GlobalVariable.mLaring 		= Math.abs((kepadatanSudut[0] - kepadatanTotal)) / kepadatanTotal;
		GlobalVariable.mTiroid 		= Math.abs((kepadatanSudut[1] - kepadatanTotal)) / kepadatanTotal;
		GlobalVariable.mBronkus 	= Math.abs((kepadatanSudut[2] - kepadatanTotal)) / kepadatanTotal;
		GlobalVariable.mAppendiks 	= Math.abs((kepadatanSudut[3] - kepadatanTotal)) / kepadatanTotal;
		GlobalVariable.mPankreas 	= Math.abs((kepadatanSudut[4] - kepadatanTotal)) / kepadatanTotal;
		GlobalVariable.mHati 		= Math.abs((kepadatanSudut[5] - kepadatanTotal)) / kepadatanTotal;
		GlobalVariable.mEmpedu 		= Math.abs((kepadatanSudut[6] - kepadatanTotal)) / kepadatanTotal;
		GlobalVariable.mGinjal 		= Math.abs((kepadatanSudut[7] - kepadatanTotal)) / kepadatanTotal;
		GlobalVariable.mDada 		= Math.abs((kepadatanSudut[8] - kepadatanTotal)) / kepadatanTotal;
		GlobalVariable.mParu 		= Math.abs((kepadatanSudut[9] - kepadatanTotal)) / kepadatanTotal;
		GlobalVariable.mBronkialis 	= Math.abs((kepadatanSudut[10] - kepadatanTotal)) / kepadatanTotal;
		GlobalVariable.mJantung 	= Math.abs((kepadatanSudut[11] - kepadatanTotal)) / kepadatanTotal;
		GlobalVariable.mLimpa 		= Math.abs((kepadatanSudut[12] - kepadatanTotal)) / kepadatanTotal;
		GlobalVariable.mKolonnaik 	= Math.abs((kepadatanSudut[13] - kepadatanTotal)) / kepadatanTotal;
		GlobalVariable.mKolonturun 	= Math.abs((kepadatanSudut[14] - kepadatanTotal)) / kepadatanTotal;
		GlobalVariable.mUsusKecil 	= Math.abs((kepadatanSudut[15] - kepadatanTotal)) / kepadatanTotal;
		GlobalVariable.mKolonSigmoid = Math.abs((kepadatanSudut[16] - kepadatanTotal)) / kepadatanTotal;
		GlobalVariable.mUsusBuntu 	= Math.abs((kepadatanSudut[17] - kepadatanTotal)) / kepadatanTotal;
		GlobalVariable.mLambung 	= Math.abs((kepadatanSudut[18] - kepadatanTotal)) / kepadatanTotal;
	}
	
	/*private boolean inside(int x, int y) {
		if (x < 0 || x >= mImageWidth || y < 0 || y >= mImageHeight)
			return false;
		return true;
	}*/
	
	private int[][] mFlood;
	
	private ArrayList<Point> mBigBlacked;
	private ArrayList<IrisPixel> mIris;
	private Point mCenter;
	
	/*private static int[] dx = {0 , 0 , 1 , -1};
	private static int[] dy = {1 , -1 , 0 , 0};*/
	
	private int mImageWidth, mImageHeight;
	
	//private ImageView mImage;
	private float mIrisRadius;
}
